package com.zx._08_网络.cpt4_ftp;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.SocketException;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

public class FTPUtul {


    public static void main(String[] args) throws IOException {
        String ip = "192.168.159.128";
        int port = 21;
        String username = "uftp";
        String password = "zhangxue";
        String ftpDir = "A/1";//服务器的文件目录，如果是根目录是"",

        String uploadFileName = "d:/1.png";

        //1.上传
        File uploadFile = new File(uploadFileName);
        boolean flag = uploadFile(ip, port, username, password, ftpDir, "3.png", uploadFile);
        System.out.println(flag);

        //2.下载
  		/*boolean file = downFile(ip, port, username, password, ftpDir, "测试.png", "e:/");
  		System.out.println(file);*/

        //3.上传文件夹
		/*try { 
	        boolean b = uploadDir(ip, port, username, password, ftpDir, "d:/新闻"); 
	        System.out.println(b); 
	    } catch (FileNotFoundException e) { 
	        e.printStackTrace(); 
	    }*/
    }

    /**
     * Description: 向FTP服务器上传单个文件
     *
     * @param url FTP服务器URL
     * @param port FTP服务器端口
     * @param username FTP登录账号
     * @param password FTP登录密码
     * @param ftpPath FTP服务器保存目录
     * @param filename 上传到FTP服务器上的文件名
     * @param file 输入流
     * @return 成功返回true，否则返回false
     */
    public static boolean uploadFile(String url, int port, String username, String password, String ftpPath,
            String filename, File file) {
        FTPClient ftp = new FTPClient();
        ByteArrayInputStream input = null;
        try {
            String ftpPathName = new String(ftpPath.getBytes(), "ISO-8859-1");
            //连接FTP服务器
            ftp.connect(url, port);
            //登录
            ftp.login(username, password);
            //判断登录是否成功
            int reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return false;
            }

            input = getInputStream(file);
            //设置缓冲区大小为ftp默认大小
            ftp.setBufferSize(ftp.getBufferSize());
            boolean b = ftp.changeWorkingDirectory(ftpPathName); //文件保存地址

            if (!b) {//如果路径不存在则创建目录
                mkdir(ftp, ftpPathName);
                ftp.changeWorkingDirectory(ftpPathName); //文件保存地址
            }
            //设置文件类型（二进制）
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
            //直接保存文件
            ftp.storeFile(new String(filename.getBytes(), "ISO-8859-1"), input);
            //注销登录
            ftp.logout();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (input != null) {
                    input.close();
                }
                if (ftp.isConnected()) {
                    ftp.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获得file的字节流，这个方法避免了FileInputStream 出现的末尾出现的中文异常
     *
     * @param file
     * @return
     * @throws IOException
     */
    private static ByteArrayInputStream getInputStream(File file) throws IOException {
        ByteArrayInputStream input = null;
        byte[] allBytes = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
        input = new ByteArrayInputStream(allBytes);
        return input;
    }

    /**
     * 上传一个一级目录的文件夹
     *
     * @param url 地址
     * @param port 端口
     * @param username 账号
     * @param password 密码
     * @param ftpPath ftp站点的路径
     * @param dirPath 文件在本地的路径
     * @return
     * @throws FileNotFoundException
     */
    public static boolean uploadDir(String url, int port, String username, String password, String ftpPath,
            String dirPath) throws FileNotFoundException {
        File f = new File(dirPath);
        if (f.isDirectory()) {
            if (ftpPath == null || ftpPath.length() == 0) {
                ftpPath = f.getName();
            } else {
                ftpPath += File.separator + f.getName();
            }
        } else {
            System.out.println("上传的必须是文件夹");
        }
        return uploadFiles(url, port, username, password, ftpPath, dirPath);
    }

    /**
     * 辅助uploadDir方法完成文件夹的上传
     *
     * @param url
     * @param port
     * @param username
     * @param password
     * @param ftpPath
     * @param dirPath
     * @return
     * @throws FileNotFoundException
     */
    private static boolean uploadFiles(String url, int port, String username, String password, String ftpPath,
            String dirPath) throws FileNotFoundException {
        File file = new File(dirPath);
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files) {
                if (f.isDirectory()) {
                    uploadFiles(url, port, username, password, ftpPath + File.separator + f.getName(),
                            f.getAbsolutePath());
                } else {
                    uploadFile(url, port, username, password, ftpPath, f.getName(), f);
                }
            }
            return true;

        }
        return false;
    }


    /**
     * Description: 从FTP服务器下载文件
     *
     * @param url FTP服务器URL
     * @param port FTP服务器端口
     * @param username FTP登录账号
     * @param password FTP登录密码
     * @param remotePath FTP服务器上的相对路径
     * @param fileName 要下载的文件名
     * @param localPath 下载后保存到本地的路径
     * @return
     */
    public static boolean downFile(String url, int port, String username, String password, String remotePath,
            String fileName, String localPath) {
        FTPClient ftp = new FTPClient();
        try {
            ftp.connect(url, port);
            //如果采用默认端口，可以使用ftp.connect(url)的方式直接连接FTP服务器
            ftp.login(username, password);//登录
            int reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return false;
            }
            ftp.changeWorkingDirectory(remotePath);//转移到FTP服务器目录
            FTPFile[] fs = ftp.listFiles();
            for (FTPFile ff : fs) {
                String encodingName = new String(ff.getName().getBytes("ISO-8859-1"), "UTF-8");
                if (encodingName.equals(fileName)) {
                    File localFile = new File(localPath + File.separator + encodingName);
                    OutputStream is = new FileOutputStream(localFile);
                    ftp.retrieveFile(ff.getName(), is);
                    is.close();
                }
            }
            ftp.logout();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
    }

    /**
     * 将FTP端文件从源位置移至到另一位置
     *
     * @param remoteFrom 原位置
     * @param remoteTo 新位置
     * @return
     * @throws IOException
     */
    public static boolean rename(FTPClient ftp, String remoteFrom, String remoteTo) throws IOException {
        boolean flag = ftp.rename(remoteFrom, remoteTo);
        return flag;
    }

    /**
     * 在FTP Server上创建目录
     *
     * @param pathname 目录路径，从ftp目录开始
     * @return
     * @throws IOException
     */
    public static boolean mkdir(FTPClient ftp, String pathname) throws IOException {
        boolean flag = ftp.makeDirectory(pathname);
        return flag;
    }

    /**
     * 创建一个ftp客户端。
     *
     * @param url 地址
     * @param port 端口
     * @param username 账号
     * @param password 密码
     * @return
     * @throws SocketException
     * @throws IOException
     */
    public static FTPClient getFTPClient(String url, int port, String username, String password)
            throws SocketException, IOException {
        FTPClient ftp = new FTPClient();
        //连接FTP服务器
        ftp.connect(url, port);
        //登录 
        ftp.login(username, password);
        //判断登录是否成功
        int reply = ftp.getReplyCode();
        if (!FTPReply.isPositiveCompletion(reply)) {
            ftp.disconnect();
            return null;
        }
        return ftp;
    }
}
